﻿using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using XiAnAirport.BUS;
using XiAnAirport.Models;

namespace XiAnAirport.ElevatorWebSocket
{
    public class WebSocketManage : IWebSocketManage
    {
        ConcurrentDictionary<string, WebSocket> _sockets;
        AutoResetEvent autoResetEvent = new AutoResetEvent(false);
        public ConcurrentDictionary<string, WebSocket> Socket
        {
            get
            {
                return _sockets;
            }
            set
            {
                _sockets = value;
            }
        }
        ConcurrentDictionary<int, ConcurrentDictionary<string, WebSocket>> _areasockets;
        ConcurrentDictionary<int, ConcurrentDictionary<string, WebSocket>> _single_elevatorsockets;
        ConcurrentDictionary<string, WebSocket> _elevatorListsockets;
        ConcurrentDictionary<string, WebSocket> _fault_reportsockets;
        ConcurrentDictionary<string, WebSocket> _homepage_sockets;
        ConcurrentDictionary<string, WebSocket> _kone_homepage_sockets;
        ConcurrentDictionary<string, WebSocket> _promptsockets;
        ConcurrentDictionary<string, WebSocket> _loginsockets;
        public ConcurrentDictionary<int, ConcurrentDictionary<string, WebSocket>> AreaSocket
        {
            get
            {
                return _areasockets;
            }
            set
            {
                _areasockets = value;
            }
        }
        public ConcurrentDictionary<int, ConcurrentDictionary<string, WebSocket>> SingleElevatorSocket
        {
            get
            {
                return _single_elevatorsockets;
            }
            set
            {
                _single_elevatorsockets = value;
            }
        }
        public ConcurrentDictionary<string, WebSocket> ElevatorListSocket
        {
            get
            {
                return _elevatorListsockets;
            }
            set
            {
                _elevatorListsockets = value;
            }
        }
        public ConcurrentDictionary<string, WebSocket> FaultReportSocket
        {
            get
            {
                return _fault_reportsockets;
            }
            set
            {
                _fault_reportsockets = value;
            }
        }

        public ConcurrentDictionary<string, WebSocket> HomePageSocket
        {
            get
            {
                return _homepage_sockets;
            }
            set
            {
                _homepage_sockets = value;
            }
        }
        public ConcurrentDictionary<string, WebSocket> KoneHomePageSocket
        {
            get
            {
                return _kone_homepage_sockets;
            }
            set
            {
                _kone_homepage_sockets = value;
            }
        }
        public ConcurrentDictionary<string, WebSocket> PromptSockets
        {
            get
            {
                return _promptsockets;
            }
            set
            {
                _promptsockets = value;
            }
        }

        public ConcurrentDictionary<string, WebSocket> LoginSockets
        {
            get
            {
                return _loginsockets;
            }
            set
            {
                _loginsockets = value;
            }
        }
        public async Task SendMessage(string Sid, string Message)
        {
            if (_sockets != null)
            {
                WebSocket socket;
                bool getSuccess = _sockets.TryGetValue(Sid, out socket);
                if (getSuccess)
                {
                    byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                    await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                }
            }
        }

        public async Task<bool> PushMessage(LiftStateALL elevatorState)
        {
            string Msg = JsonConvert.SerializeObject(elevatorState);
            await SendMessage("1", Msg);
            return false;
        }

        public async Task<bool> PushFaultMessage(string msg)
        {
            await SendMessage("2", msg);
            return false;
        }

        public async Task<bool> PushElevatorMessage(LiftStateALL elevatorState)
        {
            string Msg = JsonConvert.SerializeObject(elevatorState);
            await SendMessage("3", Msg);
            return false;
        }

        public async Task<bool> PushTwinkleMessage(LiftStateALL elevatorState)
        {
            string Msg = JsonConvert.SerializeObject(elevatorState);
            await SendMessage("4", Msg);
            return false;
        }

        public async Task SendAreaMessage(int areaid, string Message)
        {
            try
            {
                if (_areasockets != null)
                {
                    ConcurrentDictionary<string, WebSocket> _tempsockets;
                    bool getSuccess = _areasockets.TryGetValue(areaid, out _tempsockets);
                    if (getSuccess)
                    {
                        foreach (var item in _tempsockets)
                        {
                            WebSocket socket = item.Value;
                            if (socket.State.ToString() == "Open")
                            {
                                byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                                await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                            }
                            else
                            {
                                WebSocket tempsocket = item.Value;
                                _tempsockets.Remove(item.Key, out tempsocket);
                            }
                        }
                        _areasockets.TryAdd(areaid, _tempsockets);
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushAreaMessage(int areaid, LiftStateALL elevatorState)
        {
            string Msg = JsonConvert.SerializeObject(elevatorState);
            await SendAreaMessage(areaid, Msg);
            return false;
        }

        public async Task SendElevatorMessage(int elevatorid, string Message)
        {
            try
            {
                if (_single_elevatorsockets != null)
                {
                    ConcurrentDictionary<string, WebSocket> _tempsockets;
                    bool getSuccess = _single_elevatorsockets.TryGetValue(elevatorid, out _tempsockets);
                    if (getSuccess)
                    {
                        foreach (var item in _tempsockets)
                        {
                            WebSocket socket = item.Value;
                            if (socket.State.ToString() == "Open")
                            {
                                byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                                await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                            }
                            else
                            {
                                WebSocket tempsocket;
                                _tempsockets.Remove(item.Key, out tempsocket);
                            }
                        }
                        _single_elevatorsockets.TryAdd(elevatorid, _tempsockets);
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushElevatorMessage(int elevatorid, LiftStateALL elevatorState)
        {
            string Msg = JsonConvert.SerializeObject(elevatorState);
            await SendElevatorMessage(elevatorid, Msg);
            return false;
        }

        public async Task SendElevatorListMessage(string Message)
        {
            try
            {
                if (_elevatorListsockets != null)
                {
                    foreach (var item in _elevatorListsockets)
                    {
                        WebSocket socket = item.Value;
                        if (socket.State.ToString() == "Open")
                        {
                            byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                            await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                        }
                        else
                        {
                            WebSocket tempsocket;
                            _elevatorListsockets.Remove(item.Key, out tempsocket);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushElevatorListMessage(string msg)
        {
            await SendElevatorListMessage(msg);
            return false;
        }

        public async Task SendFaultReportMessage(string Message)
        {
            try
            {
                if (_fault_reportsockets != null)
                {
                    foreach (var item in _fault_reportsockets)
                    {
                        WebSocket socket = item.Value;
                        if (socket.State.ToString() == "Open")
                        {
                            byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                            await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                        }
                        else
                        {
                            WebSocket tempsocket;
                            _fault_reportsockets.Remove(item.Key, out tempsocket);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushFaultReportMessage(ElevatorFault elevatorFault)
        {
            string Msg = JsonConvert.SerializeObject(elevatorFault);
            await SendFaultReportMessage(Msg);
            return false;
        }

        public async Task SendNoticeMessage(string Message)
        {
            try
            {
                if (_homepage_sockets != null)
                {
                    foreach (var item in _homepage_sockets)
                    {
                        WebSocket socket = item.Value;
                        if (socket.State.ToString() == "Open")
                        {
                            byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                            await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                        }
                        else
                        {
                            WebSocket tempsocket;
                            _homepage_sockets.Remove(item.Key, out tempsocket);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushNoticeMessage(string message)
        {
            await SendNoticeMessage(message);
            return false;
        }

        public async Task<bool> PushKoneHomeMessage(string message)
        {
            await SendKoneHomeMessage(message);
            return false;
        }

        public async Task SendKoneHomeMessage(string Message)
        {
            try
            {
                if (_kone_homepage_sockets != null)
                {
                    foreach (var item in _kone_homepage_sockets)
                    {
                        WebSocket socket = item.Value;
                        if (socket.State.ToString() == "Open")
                        {
                            byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                            await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                        }
                        else
                        {
                            WebSocket tempsocket;
                            _kone_homepage_sockets.Remove(item.Key, out tempsocket);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushPromptMessage(string message)
        {
            await SendPromptMessage(message);
            return false;
        }

        public async Task SendPromptMessage(string Message)
        {
            try
            {
                if (_promptsockets != null)
                {
                    foreach (var item in _promptsockets)
                    {
                        WebSocket socket = item.Value;
                        if (socket.State.ToString() == "Open")
                        {
                            byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                            await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                        }
                        else
                        {
                            WebSocket tempsocket;
                            _promptsockets.Remove(item.Key, out tempsocket);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }

        public async Task<bool> PushLoginMessage(string name, string message)
        {
            await SendLoginMessage(name, message);
            return false;
        }

        public async Task SendLoginMessage(string user, string Message)
        {
            try
            {
                if (_loginsockets != null)
                {
                    foreach (var item in _loginsockets)
                    {
                        WebSocket socket = item.Value;
                        if (item.Key == user)
                        {
                            if (socket.State.ToString() == "Open")
                            {
                                byte[] bMessage = System.Text.Encoding.UTF8.GetBytes(Message);
                                await socket.SendAsync(new ArraySegment<byte>(bMessage), WebSocketMessageType.Text, true, new System.Threading.CancellationToken());
                            }
                            else
                            {
                                WebSocket tempsocket;
                                _loginsockets.Remove(item.Key, out tempsocket);
                            }
                        }

                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
        }
    }
}
